package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberDO;
import com.ssy.lingxi.member.merchant.entity.MemberRectifyDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.RoleDO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskListBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskResultBO;
import com.ssy.lingxi.member.merchant.model.constant.MemberRectifyAgreeResultEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberRectifyStatusEnum;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.*;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.*;
import com.ssy.lingxi.member.merchant.repository.MemberRectifyRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberHistoryService;
import com.ssy.lingxi.member.merchant.service.feign.IMessageFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IReportFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IWorkflowFeignService;
import com.ssy.lingxi.member.merchant.service.web.IMemberRectifyService;
import com.ssy.lingxi.member.merchant.utils.CodeUtils;
import com.ssy.lingxi.member.merchant.utils.FileObjectUtil;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.report.api.enums.MemberRectifyNoticeOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.MemberRectifyOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 会员整改服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/5/17
 */
@Service
public class MemberRectifyServiceImpl implements IMemberRectifyService {

    private static final Logger log = LoggerFactory.getLogger(MemberRectifyServiceImpl.class);

    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberRectifyRepository memberRectifyRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private IWorkflowFeignService workflowFeignService;

    @Resource
    private IBaseMemberHistoryService memberHistoryService;

    @Resource
    private IMessageFeignService messageFeignService;

    @Resource
    private IReportFeignService reportFeignService;

    @Override
    public Wrapper<List<StatusVO>> listMemberRectifyOuterStatus(HttpHeaders headers) {
        List<StatusVO> statusVOList = Stream.of(MemberRectifyStatusEnum.values()).map(e -> {
            StatusVO statusVO = new StatusVO();
            statusVO.setCode(e.getCode());
            statusVO.setMessage(e.getMessage());
            return statusVO;
        }).collect(Collectors.toList());

        return Wrapper.success(statusVOList);
    }

    @Override
    public Wrapper<List<StatusVO>> listSubMemberRectifyOuterStatus(HttpHeaders headers) {
        List<StatusVO> statusVOList = Stream.of(
                MemberRectifyStatusEnum.WAIT_RECTIFY,
                MemberRectifyStatusEnum.WAIT_CONFIRM,
                MemberRectifyStatusEnum.REJECT,
                MemberRectifyStatusEnum.APPROVE)
                .map(e -> {
                    StatusVO statusVO = new StatusVO();
                    statusVO.setCode(e.getCode());
                    statusVO.setMessage(e.getMessage());
                    return statusVO;
                }).collect(Collectors.toList());

        return Wrapper.success(statusVOList);
    }

    @Override
    public Wrapper<PageData<MemberRectifySummaryPageQueryVO>> pageSummaryMemberRectify(HttpHeaders headers, MemberAddRectifySummaryPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Page<MemberRectifyDO> pageList = basePageMemberRectify(loginUser, Objects.isNull(pageVO.getOuterStatus()) ? Collections.emptyList() : Collections.singletonList(pageVO.getOuterStatus()), pageVO);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberRectifyDO -> {
            MemberRectifySummaryPageQueryVO queryVO = new MemberRectifySummaryPageQueryVO();
            queryVO.setId(memberRectifyDO.getId());
            queryVO.setRectifyNo(memberRectifyDO.getRectifyNo());
            queryVO.setOuterStatus(memberRectifyDO.getOuterStatus());
            queryVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
            queryVO.setSubject(memberRectifyDO.getSubject());
            queryVO.setName(memberRectifyDO.getSubMember().getName());
            queryVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
            queryVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
            queryVO.setAgreeResult(memberRectifyDO.getAgreeResult());
            queryVO.setAgreeResultName(MemberRectifyAgreeResultEnum.getCodeMessage(memberRectifyDO.getAgreeResult()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员信息 - 会员详情 - 分页查询会员整改
     * @param member 上级会员
     * @param role 上级会员角色Id
     * @param subMember 下级会员
     * @param subRole 下级会员角色Id
     * @param current 当前页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberRecordRectifyVO>> pageMemberRecordRectify(MemberDO member, RoleDO role, MemberDO subMember, RoleDO subRole, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberRectifyDO> pageList = memberRectifyRepository.findAll((Specification<MemberRectifyDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("member").as(MemberDO.class), member));
            predicateList.add(cb.equal(root.get("role").as(RoleDO.class), role));
            predicateList.add(cb.equal(root.get("subMember").as(MemberDO.class), subMember));
            predicateList.add(cb.equal(root.get("subRole").as(RoleDO.class), subRole));
            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberRectifyDO -> {
            MemberRecordRectifyVO queryVO = new MemberRecordRectifyVO();
            queryVO.setId(memberRectifyDO.getId());
            queryVO.setSubject(memberRectifyDO.getSubject());
            queryVO.setRectifyTimeStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
            queryVO.setRectifyTimeEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
            queryVO.setResult(memberRectifyDO.getAgreeResult() == null ? "" : (memberRectifyDO.getAgreeResult().equals(EnableDisableStatus.ENABLE.getCode()) ? "整改通过" : "整改不通过"));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberRectifyAddPageQueryVO>> pageAddMemberRectify(HttpHeaders headers, MemberAddRectifyPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Page<MemberRectifyDO> pageList = basePageMemberRectify(loginUser, Collections.singletonList(MemberRectifyStatusEnum.WAIT_SEND.getCode()), pageVO);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberRectifyDO -> {
            MemberRectifyAddPageQueryVO queryVO = new MemberRectifyAddPageQueryVO();
            queryVO.setId(memberRectifyDO.getId());
            queryVO.setRectifyNo(memberRectifyDO.getRectifyNo());
            queryVO.setOuterStatus(memberRectifyDO.getOuterStatus());
            queryVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
            queryVO.setSubject(memberRectifyDO.getSubject());
            queryVO.setName(memberRectifyDO.getSubMember().getName());
            queryVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
            queryVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
            queryVO.setSendOrUpdateOrDel(MemberRectifyStatusEnum.WAIT_SEND.getCode().equals(memberRectifyDO.getOuterStatus()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberRectifyConfirmPageQueryVO>> pageConfirmMemberRectify(HttpHeaders headers, MemberAddRectifyPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Page<MemberRectifyDO> pageList = basePageMemberRectify(loginUser, Collections.singletonList(MemberRectifyStatusEnum.WAIT_CONFIRM.getCode()), pageVO);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberRectifyDO -> {
            MemberRectifyConfirmPageQueryVO queryVO = new MemberRectifyConfirmPageQueryVO();
            queryVO.setId(memberRectifyDO.getId());
            queryVO.setRectifyNo(memberRectifyDO.getRectifyNo());
            queryVO.setOuterStatus(memberRectifyDO.getOuterStatus());
            queryVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
            queryVO.setSubject(memberRectifyDO.getSubject());
            queryVO.setName(memberRectifyDO.getSubMember().getName());
            queryVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
            queryVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
            queryVO.setConfirm(MemberRectifyStatusEnum.WAIT_CONFIRM.getCode().equals(memberRectifyDO.getOuterStatus()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberRectifyManagePageQueryVO>> pageManageMemberRectify(HttpHeaders headers, MemberAddRectifySummaryPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        Page<MemberRectifyDO> pageList = memberRectifyRepository.findAll((Specification<MemberRectifyDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("subMember"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("subRole"), loginUser.getMemberRoleId()));

            if (Objects.nonNull(pageVO.getOuterStatus())) {
                predicateList.add(cb.equal(root.get("outerStatus"), pageVO.getOuterStatus()));
            }

            if (StringUtils.isNotEmpty(pageVO.getName())) {
                Join<MemberRectifyDO, MemberDO> upperMemberJoin = root.join("member", JoinType.LEFT);
                predicateList.add(cb.like(upperMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getRectifyDayStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateStart(pageVO.getRectifyDayStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("rectifyTimeStart"), startDate));
            }

            if (Objects.nonNull(pageVO.getRectifyDayEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateEnd(pageVO.getRectifyDayEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("rectifyTimeEnd"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberRectifyDO -> {
            MemberRectifyManagePageQueryVO queryVO = new MemberRectifyManagePageQueryVO();
            queryVO.setId(memberRectifyDO.getId());
            queryVO.setRectifyNo(memberRectifyDO.getRectifyNo());
            queryVO.setOuterStatus(memberRectifyDO.getOuterStatus());
            queryVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
            queryVO.setSubject(memberRectifyDO.getSubject());
            queryVO.setUpperMemberName(memberRectifyDO.getMember().getName());
            queryVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
            queryVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
            queryVO.setAgreeResult(memberRectifyDO.getAgreeResult());
            queryVO.setAgreeResultName(MemberRectifyAgreeResultEnum.getCodeMessage(memberRectifyDO.getAgreeResult()));
            List<Integer> statusList = Arrays.asList(MemberRectifyStatusEnum.WAIT_RECTIFY.getCode(), MemberRectifyStatusEnum.REJECT.getCode());
            queryVO.setRectifyOrUpdate(statusList.contains(memberRectifyDO.getOuterStatus()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    private Page<MemberRectifyDO> basePageMemberRectify(UserLoginCacheDTO loginUser, List<Integer> statusList, MemberAddRectifyPageVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        return memberRectifyRepository.findAll((Specification<MemberRectifyDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("member"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("role"), loginUser.getMemberRoleId()));

            if (!CollectionUtils.isEmpty(statusList)) {
                predicateList.add(cb.and(root.get("outerStatus").in(statusList)));
            }

            if (StringUtils.isNotEmpty(pageVO.getName())) {
                Join<MemberRectifyDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                predicateList.add(cb.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getRectifyDayStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateStart(pageVO.getRectifyDayStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("rectifyTimeStart"), startDate));
            }

            if (Objects.nonNull(pageVO.getRectifyDayEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateEnd(pageVO.getRectifyDayEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("rectifyTimeEnd"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);
    }

    @Override
    public Wrapper<MemberRectifyVO> getMemberRectify(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberRectifyVO memberRectifyVO = new MemberRectifyVO();
        memberRectifyVO.setId(memberRectifyDO.getId());
        memberRectifyVO.setRectifyNo(memberRectifyDO.getRectifyNo());
        memberRectifyVO.setOuterStatus(memberRectifyDO.getOuterStatus());
        memberRectifyVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
        memberRectifyVO.setSubject(memberRectifyDO.getSubject());
        memberRectifyVO.setSubMemberId(memberRectifyDO.getSubMember().getId());
        memberRectifyVO.setSubRoleId(memberRectifyDO.getSubRole().getId());
        memberRectifyVO.setName(memberRectifyDO.getSubMember().getName());
        memberRectifyVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
        memberRectifyVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
        memberRectifyVO.setReason(memberRectifyDO.getReason());
        memberRectifyVO.setRequire(memberRectifyDO.getRequire());
        memberRectifyVO.setAttachments(FileObjectUtil.toVOList(memberRectifyDO.getAttachments()));

        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listExternalProcessSteps(memberRectifyDO.getRole().getId(), memberRectifyDO.getSubRole().getId(), ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }


        if (StringUtils.isBlank(memberRectifyDO.getTaskId()) && MemberRectifyStatusEnum.APPROVE.getCode().equals(memberRectifyDO.getOuterStatus())) {
            memberRectifyVO.setCurrentOuterStep(4);
        } else {
            memberRectifyVO.setCurrentOuterStep(result.getData().getCurrentStep());
        }
        memberRectifyVO.setOuterVerifySteps(result.getData().getStepList());
        memberRectifyVO.setOuterHistory(memberHistoryService.listMemberRectifyOuterHistory(memberRectifyDO.getId()));
        memberRectifyVO.setInnerHistory(memberHistoryService.listMemberRectifyInnerHistory(memberRectifyDO.getId()));

        return Wrapper.success(memberRectifyVO);
    }

    @Override
    public Wrapper<MemberRectifyResultVO> getMemberRectifyResult(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberRectifyResultVO memberRectifyVO = new MemberRectifyResultVO();
        memberRectifyVO.setId(memberRectifyDO.getId());
        memberRectifyVO.setRectifyNo(memberRectifyDO.getRectifyNo());
        memberRectifyVO.setOuterStatus(memberRectifyDO.getOuterStatus());
        memberRectifyVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
        memberRectifyVO.setSubject(memberRectifyDO.getSubject());
        memberRectifyVO.setSubMemberId(memberRectifyDO.getSubMember().getId());
        memberRectifyVO.setSubRoleId(memberRectifyDO.getSubRole().getId());
        memberRectifyVO.setName(memberRectifyDO.getSubMember().getName());
        memberRectifyVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
        memberRectifyVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
        memberRectifyVO.setReason(memberRectifyDO.getReason());
        memberRectifyVO.setRequire(memberRectifyDO.getRequire());
        memberRectifyVO.setAttachments(FileObjectUtil.toVOList(memberRectifyDO.getAttachments()));
        memberRectifyVO.setReportDigest(memberRectifyDO.getReportDigest());
        memberRectifyVO.setReportAttachments(FileObjectUtil.toVOList(memberRectifyDO.getReportAttachments()));
        memberRectifyVO.setAgreeResult(memberRectifyDO.getAgreeResult());
        memberRectifyVO.setResultRemark(memberRectifyDO.getResultRemark());

        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listExternalProcessSteps(memberRectifyDO.getRole().getId(), memberRectifyDO.getSubRole().getId(), ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        if (StringUtils.isBlank(memberRectifyDO.getTaskId()) && MemberRectifyStatusEnum.APPROVE.getCode().equals(memberRectifyDO.getOuterStatus())) {
            memberRectifyVO.setCurrentOuterStep(4);
        } else {
            memberRectifyVO.setCurrentOuterStep(result.getData().getCurrentStep());
        }
        memberRectifyVO.setOuterVerifySteps(result.getData().getStepList());
        memberRectifyVO.setOuterHistory(memberHistoryService.listMemberRectifyOuterHistory(memberRectifyDO.getId()));
        memberRectifyVO.setInnerHistory(memberHistoryService.listMemberRectifyInnerHistory(memberRectifyDO.getId()));

        return Wrapper.success(memberRectifyVO);
    }

    @Override
    public Wrapper<MemberRectifyManageVO> getMemberRectifyManage(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (memberRectifyDO == null
                || !memberRectifyDO.getSubMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getSubRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberRectifyManageVO memberRectifyVO = new MemberRectifyManageVO();
        memberRectifyVO.setId(memberRectifyDO.getId());
        memberRectifyVO.setRectifyNo(memberRectifyDO.getRectifyNo());
        memberRectifyVO.setOuterStatus(memberRectifyDO.getOuterStatus());
        memberRectifyVO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(memberRectifyDO.getOuterStatus()));
        memberRectifyVO.setSubject(memberRectifyDO.getSubject());
        memberRectifyVO.setMemberId(memberRectifyDO.getMember().getId());
        memberRectifyVO.setRoleId(memberRectifyDO.getSubRole().getId());
        memberRectifyVO.setUpperMemberName(memberRectifyDO.getMember().getName());
        memberRectifyVO.setRectifyDayStart(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeStart()));
        memberRectifyVO.setRectifyDayEnd(DateTimeUtil.formatDate(memberRectifyDO.getRectifyTimeEnd()));
        memberRectifyVO.setReason(memberRectifyDO.getReason());
        memberRectifyVO.setRequire(memberRectifyDO.getRequire());
        memberRectifyVO.setAttachments(FileObjectUtil.toVOList(memberRectifyDO.getAttachments()));
        memberRectifyVO.setReportDigest(memberRectifyDO.getReportDigest());
        memberRectifyVO.setReportAttachments(FileObjectUtil.toVOList(memberRectifyDO.getReportAttachments()));
        memberRectifyVO.setAgreeResult(memberRectifyDO.getAgreeResult());
        memberRectifyVO.setResultRemark(memberRectifyDO.getResultRemark());

        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listExternalProcessSteps(memberRectifyDO.getRole().getId(), memberRectifyDO.getSubRole().getId(), ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        if (StringUtils.isBlank(memberRectifyDO.getTaskId()) && MemberRectifyStatusEnum.APPROVE.getCode().equals(memberRectifyDO.getOuterStatus())) {
            memberRectifyVO.setCurrentOuterStep(4);
        } else {
            memberRectifyVO.setCurrentOuterStep(result.getData().getCurrentStep());
        }
        memberRectifyVO.setOuterVerifySteps(result.getData().getStepList());
        memberRectifyVO.setOuterHistory(memberHistoryService.listMemberRectifyOuterHistory(memberRectifyDO.getId()));

        return Wrapper.success(memberRectifyVO);
    }

    @Override
    public Wrapper<Void> updateReportMemberRectify(HttpHeaders headers, MemberRectifyReportVO reportVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(reportVO.getId()).orElse(null);
        if (memberRectifyDO == null
                || !memberRectifyDO.getSubMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getSubRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        memberRectifyDO.setReportDigest(reportVO.getReportDigest());
        memberRectifyDO.setReportAttachments(FileObjectUtil.toBOList(reportVO.getReportAttachments()));

        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> addMemberRectify(HttpHeaders headers, MemberRectifyAddVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(
                loginUser.getMemberId(), loginUser.getMemberRoleId(),
                addVO.getSubMemberId(), addVO.getSubRoleId());

        if (relationDO == null
                || !relationDO.getMemberId().equals(loginUser.getMemberId())
                || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if (!MemberStatusEnum.NORMAL.getCode().equals(relationDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRectifyDO memberRectifyDO = new MemberRectifyDO();
        memberRectifyDO.setSubject(addVO.getSubject());
        memberRectifyDO.setSubMember(relationDO.getSubMember());
        memberRectifyDO.setSubRole(relationDO.getSubRole());
        memberRectifyDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberRectifyDO.setMember(relationDO.getMember());
        memberRectifyDO.setRole(relationDO.getRole());
        memberRectifyDO.setCreateTime(LocalDateTime.now());
        memberRectifyDO.setRectifyTimeStart(DateTimeUtil.parseConcatDateTime(addVO.getRectifyDayStart()));
        memberRectifyDO.setRectifyTimeEnd(DateTimeUtil.parseConcatDateTime(addVO.getRectifyDayEnd()));
        memberRectifyDO.setReason(addVO.getReason());
        memberRectifyDO.setRequire(addVO.getRequire());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        memberRectifyDO.setRectifyNo("RN" + CodeUtils.digits32(memberRectifyDO.getId(), 4));
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.startMemberProcess(ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY,
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberRectifyDO.getId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员整改新增, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberRectifyDO.setInnerStatus(result.getData().getInnerStatus());
        memberRectifyDO.setOuterStatus(result.getData().getInnerStatus());
        memberRectifyDO.setTaskId(result.getData().getTaskId());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        // 首页统计
        reportFeignService.executeIncreaseReport(OperateDataSourceEnum.MEMBER_RECTIFY.getCode(), MemberRectifyOperateTypeEnum.TO_BE_SEND_NOTICE_COUNT.getCode(),
                memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId());

        // 发送消息
        messageFeignService.sendSystemMessage(memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId(),
                MessageTemplateCode.mc_rectify_notification, Arrays.asList(memberRectifyDO.getRole().getRoleName(), memberRectifyDO.getMember().getName()));

        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> updateMemberRectify(HttpHeaders headers, MemberRectifyUpdateVO updateVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(updateVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberRectifyStatusEnum.WAIT_SEND.getCode().equals(memberRectifyDO.getOuterStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(
                loginUser.getMemberId(), loginUser.getMemberRoleId(),
                updateVO.getSubMemberId(), updateVO.getSubRoleId());
        if (relationDO == null
                || !relationDO.getMemberId().equals(loginUser.getMemberId())
                || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        memberRectifyDO.setSubject(updateVO.getSubject());
        memberRectifyDO.setSubMember(relationDO.getSubMember());
        memberRectifyDO.setSubRole(relationDO.getSubRole());
        memberRectifyDO.setAttachments(FileObjectUtil.toBOList(updateVO.getAttachments()));
        memberRectifyDO.setMember(relationDO.getMember());
        memberRectifyDO.setRole(relationDO.getRole());
        memberRectifyDO.setCreateTime(LocalDateTime.now());
        memberRectifyDO.setRectifyTimeStart(DateTimeUtil.parseConcatDateTime(updateVO.getRectifyDayStart()));
        memberRectifyDO.setRectifyTimeEnd(DateTimeUtil.parseConcatDateTime(updateVO.getRectifyDayEnd()));
        memberRectifyDO.setReason(updateVO.getReason());
        memberRectifyDO.setRequire(updateVO.getRequire());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> deleteMemberRectify(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)
                || !memberRectifyDO.getMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberRectifyStatusEnum.WAIT_SEND.getCode().equals(memberRectifyDO.getOuterStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        memberRectifyRepository.delete(memberRectifyDO);

        // 首页统计
        reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_RECTIFY.getCode(), MemberRectifyOperateTypeEnum.TO_BE_SEND_NOTICE_COUNT.getCode(),
                memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> sendMemberRectify(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)
                || !memberRectifyDO.getMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberRectifyStatusEnum.WAIT_SEND.getCode().equals(memberRectifyDO.getOuterStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(
                memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId());
        if (Objects.isNull(relationDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if (!MemberStatusEnum.NORMAL.getCode().equals(relationDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_STATUS_INCORRECT_OPERATE_INVALID);
        }

        List<Integer> statusList = Arrays.asList(MemberStatusEnum.NORMAL.getCode(), MemberStatusEnum.CORRECTING.getCode());
        if (!statusList.contains(relationDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_UPPER_MEMBER_STATUS_IS_NOT_NORMAL);
        }

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberRectifyDO.getId(), ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员整改发送, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberRectifyDO.setInnerStatus(result.getData().getInnerStatus());
        memberRectifyDO.setOuterStatus(result.getData().getInnerStatus());
        memberRectifyDO.setTaskId(result.getData().getTaskId());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        //修改会员关系的状态
        if (MemberStatusEnum.NORMAL.getCode().equals(relationDO.getStatus())) {
            relationDO.setStatus(MemberStatusEnum.CORRECTING.getCode());
            relationRepository.saveAndFlush(relationDO);
        }

        // 首页统计
        reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_RECTIFY.getCode(), MemberRectifyOperateTypeEnum.TO_BE_SEND_NOTICE_COUNT.getCode(), memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId(),
                OperateDataSourceEnum.MEMBER_RECTIFY_NOTICE.getCode(), MemberRectifyNoticeOperateTypeEnum.TO_BE_RECTIFY_COUNT.getCode(), memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId());

        // 发送消息
        messageFeignService.sendSystemMessage(memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                MessageTemplateCode.mc_rectify_wait_rectify, Arrays.asList(memberRectifyDO.getRole().getRoleName(), memberRectifyDO.getMember().getName()));

        memberHistoryService.saveMemberRectifyOuterHistory(loginUser, memberRectifyDO.getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                memberRectifyDO.getOuterStatus(), result.getData().getOperation(), "");

        memberHistoryService.saveMemberRectifyInnerHistory(loginUser, memberRectifyDO.getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                memberRectifyDO.getOuterStatus(), result.getData().getOperation(), "");

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> rectifyMemberRectify(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(idVO.getId()).orElse(null);
        if (memberRectifyDO == null
                || !memberRectifyDO.getSubMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getSubRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (CollectionUtils.isEmpty(memberRectifyDO.getReportAttachments())
                || CollectionUtils.isEmpty(memberRectifyDO.getReportAttachments().stream().filter(fileBO -> StringUtils.isNotBlank(fileBO.getUrl())).collect(Collectors.toList()))) {
            return Wrapper.fail(ResponseCode.MC_MS_RECTIFY_REPORT_NO_UPLOAD);
        }

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberRectifyDO.getId(), ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员整改进行整改, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberRectifyDO.setInnerStatus(result.getData().getInnerStatus());
        memberRectifyDO.setOuterStatus(result.getData().getInnerStatus());
        memberRectifyDO.setTaskId(result.getData().getTaskId());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        // 首页统计
        reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_RECTIFY_NOTICE.getCode(), MemberRectifyNoticeOperateTypeEnum.TO_BE_RECTIFY_COUNT.getCode(), memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                OperateDataSourceEnum.MEMBER_RECTIFY.getCode(), MemberRectifyOperateTypeEnum.TO_BE_CONFIRM_NOTICE_COUNT.getCode(), memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId());

        // 发送消息
        messageFeignService.sendSystemMessage(memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId(),
                MessageTemplateCode.mc_rectify_result_confirm, Arrays.asList(memberRectifyDO.getRole().getRoleName(), memberRectifyDO.getMember().getName()));

        memberHistoryService.saveMemberRectifyOuterHistory(loginUser, memberRectifyDO.getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                memberRectifyDO.getOuterStatus(), result.getData().getOperation(), "");

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> confirmMemberRectify(HttpHeaders headers, CommonAgreeVO agreeVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRectifyDO memberRectifyDO = memberRectifyRepository.findById(agreeVO.getId()).orElse(null);
        if (Objects.isNull(memberRectifyDO)
                || !memberRectifyDO.getMember().getId().equals(loginUser.getMemberId())
                || !memberRectifyDO.getRole().getId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberRelationDO memberRelationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(
                memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId());
        if (Objects.isNull(memberRelationDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }
        if (!MemberStatusEnum.CORRECTING.getCode().equals(memberRelationDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_RECTIFY_PROCESS_KEY, memberRectifyDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberRectifyDO.getId(), agreeVO.getAgree());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员整改确认, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberRectifyDO.setInnerStatus(result.getData().getInnerStatus());
        memberRectifyDO.setOuterStatus(result.getData().getInnerStatus());
        memberRectifyDO.setTaskId(result.getData().getTaskId());
        memberRectifyDO.setAgreeResult(agreeVO.getAgree());
        memberRectifyDO.setResultRemark(agreeVO.getReason());
        memberRectifyRepository.saveAndFlush(memberRectifyDO);

        //修改会员关系的状态
        if (EnableDisableStatus.ENABLE.getCode().equals(agreeVO.getAgree())) {
            memberRelationDO.setStatus(MemberStatusEnum.NORMAL.getCode());
            relationRepository.saveAndFlush(memberRelationDO);
        }

        if (EnableDisableStatus.ENABLE.getCode().equals(agreeVO.getAgree())) {
            // 首页统计
            reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_RECTIFY.getCode(), MemberRectifyOperateTypeEnum.TO_BE_CONFIRM_NOTICE_COUNT.getCode(),
                    memberRectifyDO.getMember().getId(), memberRectifyDO.getRole().getId());
        } else {
            // 首页统计
            reportFeignService.executeIncreaseReport(OperateDataSourceEnum.MEMBER_RECTIFY_NOTICE.getCode(), MemberRectifyNoticeOperateTypeEnum.TO_BE_RECTIFY_COUNT.getCode(),
                    memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                    MessageTemplateCode.mc_rectify_wait_rectify, Arrays.asList(memberRectifyDO.getRole().getRoleName(), memberRectifyDO.getMember().getName()));
        }

        memberHistoryService.saveMemberRectifyOuterHistory(loginUser, memberRectifyDO.getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                memberRectifyDO.getOuterStatus(), result.getData().getOperation(), agreeVO.getReason());

        memberHistoryService.saveMemberRectifyInnerHistory(loginUser, memberRectifyDO.getId(),
                memberRectifyDO.getSubMember().getId(), memberRectifyDO.getSubRole().getId(),
                memberRectifyDO.getOuterStatus(), result.getData().getOperation(), agreeVO.getReason());

        return Wrapper.success();
    }
}
